package com.zenjava.update;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AppProfileReader extends DefaultHandler
{
    private final static Logger LOGGER = Logger.getLogger(AppProfileReader.class.getName());

    public static final SimpleDateFormat RELEASE_DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss zzz");

    private AppProfile appProfile;
    private StringBuilder text;

    public AppProfile read(URL url) throws IOException
    {
        this.appProfile = null;
        this.text = new StringBuilder();
        InputStream in = null;
        try
        {
            if ("file".equalsIgnoreCase(url.getProtocol()))
            {
                in = new FileInputStream(url.getFile());
            }
            else
            {
                in = url.openStream();
            }
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            SAXParser saxParser = saxParserFactory.newSAXParser();
            saxParser.parse(in, this);
            AppProfile result = appProfile;
            this.appProfile = null;
            return result;
        }
        catch (ParserConfigurationException e)
        {
            throw new IOException("Error loading XML Parser", e);
        }
        catch (SAXException e)
        {
            throw new IOException("Error parsing XML", e);
        }
        finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (Exception e)
                {
                    LOGGER.warning("Unable to close XML stream: " + e.getMessage());
                }
            }
        }
    }

    public void startElement(String uri, String localName, String qName, Attributes attributes)
    {
        if (qName.equalsIgnoreCase("application"))
        {
            this.appProfile = new AppProfile();
        }
    }

    public void endElement(String uri, String localName, String qName)
    {
        if (this.appProfile == null)
        {
            return;
        }

        if (qName.equalsIgnoreCase("name"))
        {
            this.appProfile.setName(this.text.toString().trim());
        }
        else if (qName.equalsIgnoreCase("version"))
        {
            this.appProfile.setVersion(this.text.toString().trim());
        }
        else if (qName.equalsIgnoreCase("description"))
        {
            this.appProfile.setDescription(this.text.toString().trim());
        }
        else if (qName.equalsIgnoreCase("releaseNotesUrl"))
        {
            String url = this.text.toString().trim();
            try
            {
                this.appProfile.setReleaseNotesUrl(new URL(url));
            }
            catch (MalformedURLException e)
            {
                LOGGER.log(Level.SEVERE, String.format("Unable to parse 'releaseNotesUrl': %s", url), e);
            }
        }
        else if (qName.equalsIgnoreCase("releaseDate"))
        {
            String date = this.text.toString().trim();
            try
            {
                this.appProfile.setReleaseDate(RELEASE_DATE_FORMAT.parse(date));
            }
            catch (ParseException e)
            {
                LOGGER.log(Level.SEVERE, String.format("Unable to parse 'releaseDate': %s", date), e);
            }
        }
        else if (qName.equalsIgnoreCase("releaseUrl"))
        {
            String url = this.text.toString().trim();
            try
            {
                this.appProfile.setReleaseUrl(new URL(url));
            }
            catch (MalformedURLException e)
            {
                LOGGER.log(Level.SEVERE, String.format("Unable to parse 'releaseUrl': %s", url), e);
            }
        }
        else if (qName.equalsIgnoreCase("fullUpdateUrl"))
        {
            String url = this.text.toString().trim();
            try
            {
                this.appProfile.setFullUpdateUrl(new URL(url));
            }
            catch (MalformedURLException e)
            {
                LOGGER.log(Level.SEVERE, String.format("Unable to parse 'fullUpdateUrl': %s", url), e);
            }
        }

        this.text.setLength(0);
    }

    public void characters(char[] ch, int start, int length)
    {
        this.text.append(ch, start, length);
    }
}
